package com.tfjybj.itoo.exam.provider.service.impl;

import com.dmsdbj.itoo.tool.base.service.impl.BaseServicePlusImpl;
import com.dmsdbj.itoo.tool.business.ItooResult;
import com.dmsdbj.itoo.tool.uuid.BaseUuidUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tfjybj.itoo.exam.entity.ExamNoticeEntity;
import com.tfjybj.itoo.exam.entity.StudentEntity;
import com.tfjybj.itoo.exam.model.ExamNoticeErrorTemplate;
import com.tfjybj.itoo.exam.model.ExamNoticeModel;
import com.tfjybj.itoo.exam.model.ExamNoticeTemplate;
import com.tfjybj.itoo.exam.provider.dao.ExamNoticeDao;
import com.tfjybj.itoo.exam.provider.service.ExamNoticeService;
import com.tfjybj.itoo.exam.provider.service.StudentService;
import lombok.extern.slf4j.Slf4j;
import org.jplus.hyberbin.excel.utils.ExcelUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.*;


/**
 * ExamNoticeService接口实现类
 * ${base}表
 *
 * @author 贾建清
 * @version 2.0.0
 * @since 2.0.0 2018-12-26 20:56:50
 */
@Service("examNoticeService")
@Slf4j
public class ExamNoticeServiceImpl extends BaseServicePlusImpl<ExamNoticeDao, ExamNoticeEntity> implements ExamNoticeService {

    //region 模板生成
    @Resource
    private ExamNoticeDao examNoticeDao;

    @Resource
    private RedisTemplate<String, ExamNoticeErrorTemplate> redisTemplate;

    @Resource
    private StudentService studentService;

    //endregion

    /* **********************************以下为非模板生成的内容********************************* */

    /**
     * 导入学生考试信息
     *
     * @param multipartFile 文件
     * @param request       要求
     * @param response      返回
     * @return ItooResult
     * @author 贾建清
     * @since 2.0.0 2018-12-27 11:48:05
     */
    @Override
    public ItooResult importTemplate(MultipartFile multipartFile, HttpServletRequest request, HttpServletResponse response) {
        response.setContentType("UTF-8");
        //日期转换字符串的格式
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd");
        try {
            //校验文件是否存在
            String fileName = multipartFile.getOriginalFilename();
            if (fileName == null) {
                log.error("导入失败,fileName is null!");
                return ItooResult.build(ItooResult.FAIL, "传入的文件为空！");
            }

            //excel解析List
            Map<Serializable, Serializable> map = new HashMap<>(4);
            //excel中的sheet的名称
            map.put("sheetName", "考生考试信息");
            map.put("Class", ExamNoticeTemplate.class);
            List<ExamNoticeTemplate> examNoticeTemplateList = ExcelUtil.importExcel(Objects.requireNonNull(fileName), map, request, response);
            if (examNoticeTemplateList.size() == 0) {
                return ItooResult.build(ItooResult.FAIL, "导入的数据为空，请填写！");
            }
            //定义导入错误数据集合并存redis中形式<String,ExamNoticeTemplate>
            List<ExamNoticeErrorTemplate> errorExamNoticeList = new ArrayList<>();
            String errorListId = BaseUuidUtils.base58Uuid();
            Long size = redisTemplate.opsForZSet().size(errorListId);
            size = size == null ? 0L : size;

            //循环处理数据
            for (ExamNoticeTemplate excelExamNotice : examNoticeTemplateList) {
                //约束：StudentNo，studentName必填，同时要导入StudentNo不能与数据库中的其他StudentNo相同
                if (!this.verify(excelExamNotice)) {
                    ExamNoticeErrorTemplate examNoticeErrorTemplate = new ExamNoticeErrorTemplate();
                    BeanUtils.copyProperties(excelExamNotice, examNoticeErrorTemplate);
                    examNoticeErrorTemplate.setExamStartTime(simpleDateFormat.format(excelExamNotice.getExamStartTime()));

                    errorExamNoticeList.add(examNoticeErrorTemplate);
                    redisTemplate.opsForZSet().add(errorListId, examNoticeErrorTemplate, size + 1);
                    continue;
                }
                //通过学生学号查询学生id
                String studentNo = excelExamNotice.getStudentNo();
                StudentEntity studentEntity = studentService.findByStudentNo(studentNo);

                //new出FooEntity对象,通过BeanUtils把相同属性进行拷贝,然后处理不能拷贝的特殊属性.
                ExamNoticeEntity examNoticeEntity = new ExamNoticeEntity();
                BeanUtils.copyProperties(excelExamNotice, examNoticeEntity);
                examNoticeEntity.setStudentId(studentEntity.getId());
                examNoticeEntity.setProfessionId(studentEntity.getProfessionId());
                examNoticeEntity.setAcademyId(studentEntity.getAcademyId());

                //保存到数据库
                this.save(examNoticeEntity);
            }

            //不符合条件的信息返回
            if (errorExamNoticeList.size() > 0) {
                return ItooResult.build("0001", "部分导入失败", errorListId);
            }
        } catch (Exception ex) {
            return ItooResult.build(ItooResult.FAIL, "导入数据异常！", ex);
        }
        return ItooResult.build(ItooResult.SUCCESS, "导入考生成功");

    }

    /**
     * 批量导入前验证数据是否符合要求
     *
     * @param examNoticeTemplate
     * @return true:符合导入要求，false：不符合
     * @author 贾建清
     * @since 2.0.0 2018-12-27 20:09:49
     */
    private boolean verify(ExamNoticeTemplate examNoticeTemplate) {
        //判断非空字段是否有值.
        if (StringUtils.isEmpty(examNoticeTemplate.getStudentNo())) {
            examNoticeTemplate.setFailReason("studentNo未填写");
            log.warn("导入失败,studentNo未填写,excelExamNoticeEntity-{}", examNoticeTemplate);
            return false;
        }
        if (StringUtils.isEmpty(examNoticeTemplate.getStudentName())) {
            examNoticeTemplate.setFailReason("studentName未填写");
            log.warn("导入失败,studentName未填写,excelExamNoticeEntity-{}", examNoticeTemplate);
            return false;
        }
        //判断学生学号是否重复
//        if (examNoticeDao.queryByStudentNo(examNoticeTemplate.getStudentNo()).size() > 0) {
//            examNoticeTemplate.setFailReason("studentNo已存在");
//            log.warn("导入失败,studentNo已存在,excelExamNoticeEntity-{}", examNoticeTemplate);
//            return false;
//        }

        return true;
    }

    /**
     * 根据errorListId导出未成功导入的信息
     *
     * @param errorListId 为成功导入的分组id
     * @param response    响应
     * @return 导出结果
     * @author 贾建清
     * @since 2.0.0 2018-12-27 21:16:29
     */
    @Override
    public boolean exportErrorList(String errorListId, HttpServletResponse response) {
        //redis取出没有成功导入的人员信息
        Set<ExamNoticeErrorTemplate> set = redisTemplate.opsForZSet().range(errorListId, 0, -1);
        if (set == null || set.isEmpty()) {
            return false;
        }
        List<ExamNoticeErrorTemplate> examNoticeErrorTemplates = new ArrayList<>(set);
        //清空redis数据
        redisTemplate.delete(errorListId);

        //导出
        if (examNoticeErrorTemplates.size() == 0) {
            return false;
        }
        Map<Serializable, Serializable> errorMap = new HashMap<>(16);
        errorMap.put("name", "未导入的信息");
        errorMap.put("sheetName", "考生考试信息");
        errorMap.put("title", "未导入的信息");
        errorMap.put("columns", new String[]{"studentName", "studentNo", "academyName", "profession", "className", "course", "examStartTime", "examLength", "placeName", "state", "failReason"});
        errorMap.put("dataList", (Serializable) examNoticeErrorTemplates);
        try {
            ExcelUtil.exportExcel(errorMap, response);
        } catch (Exception e) {
            log.error("根据errorListId导出未成功导入的信息导出错误", e);
            return false;
        }
        return true;
    }


    /**
     * 根据课程查询该课程内的人员
     *
     * @return
     */
    @Override
    public PageInfo<ExamNoticeModel> queryNoticeByCourse(String course, Integer pageNo, Integer pageSize) {
        PageHelper.startPage(pageNo, pageSize);
        List<ExamNoticeModel> examNoticeModelList = examNoticeDao.queryNoticeByCourse(course);
        return new PageInfo<>(examNoticeModelList);
    }

    /**
     * 高级搜索
     *
     * @param examNoticeModel
     * @param pageNo
     * @param pageSize
     * @return
     */
    @Override
    public PageInfo<ExamNoticeModel> queryNoticeByInfo(Integer pageNo, Integer pageSize, ExamNoticeModel examNoticeModel) {
        PageHelper.startPage(pageNo, pageSize);
        List<ExamNoticeModel> examNoticeModelList = examNoticeDao.queryNoticeByInfo(examNoticeModel);
        return new PageInfo<>(examNoticeModelList);
    }


    /**
     * 根据课程导出考生信息
     *
     * @param response 响应
     * @param course   课程
     * @return 是否导出成功
     * @author 贾建清
     * @since 2.0.0 2018-12-28 14:40:26
     */
    @Override
    public boolean exportExamByLikeCourse(String course, HttpServletResponse response) {
        //日期转换字符串的格式
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd");

        //获得要导出的ExamNoticeList
        List<ExamNoticeModel> examNoticeModels = examNoticeDao.queryNoticeByCourse(course);
        List<ExamNoticeErrorTemplate> examNoticeErrorTemplates = new ArrayList<>();
        for (ExamNoticeModel examNoticeModel : examNoticeModels) {
            ExamNoticeErrorTemplate examNoticeErrorTemplate = new ExamNoticeErrorTemplate();
            BeanUtils.copyProperties(examNoticeModel, examNoticeErrorTemplate);
            examNoticeErrorTemplate.setExamStartTime(simpleDateFormat.format(examNoticeModel.getExamStartTime()));
            examNoticeErrorTemplate.setCourse(examNoticeModel.getCourse());
            examNoticeErrorTemplates.add(examNoticeErrorTemplate);
        }
        //导出
        Map<Serializable, Serializable> errorMap = new HashMap<>(16);
        errorMap.put("name", "考生考试信息");
        errorMap.put("sheetName", "考生考试信息");
        errorMap.put("title", "考生考试信息");
        errorMap.put("columns", new String[]{"studentName", "studentNo", "academyName", "profession", "className", "course", "examStartTime", "examLength", "placeName", "state"});
        errorMap.put("dataList", (Serializable) examNoticeErrorTemplates);
        try {
            ExcelUtil.exportExcel(errorMap, response);
        } catch (Exception e) {
            log.error("根据课程导出考生信息导出错误", e);
            return false;
        }
        return true;
    }

    /**
     * 下载考生考试模板，批量导入使用
     *
     * @param response 响应
     * @return 下载模板是否成功
     * @author 贾建清
     * @since 2.0.0 2018-12-28 20:38:36
     */
    @Override
    public boolean downTemplate(HttpServletResponse response) {
        Map<Serializable, Serializable> map = new HashMap<>(16);
        List<ExamNoticeErrorTemplate> examNoticeErrorTemplateList = new ArrayList<>();
        ExamNoticeErrorTemplate examNoticeErrorTemplate = new ExamNoticeErrorTemplate();
        examNoticeErrorTemplate.setStudentName("张晓雅");
        examNoticeErrorTemplate.setStudentNo("11080334002");
        examNoticeErrorTemplate.setAcademyName("生命科学学院");
        examNoticeErrorTemplate.setProfession("生物科学");
        examNoticeErrorTemplate.setClassName("17级生物科学");
        examNoticeErrorTemplate.setCourse("思想");
        examNoticeErrorTemplate.setExamStartTime("2018/12/28 11:43:08");
        examNoticeErrorTemplate.setExamLength(60);
        examNoticeErrorTemplate.setPlaceName("三合班");
        examNoticeErrorTemplate.setState(0);
        examNoticeErrorTemplateList.add(examNoticeErrorTemplate);
        //excel设置
        map.put("sheetName", "考生考试信息");
        map.put("columns", new String[]{"studentName", "studentNo", "academyName", "profession", "className", "course", "examStartTime", "examLength", "placeName", "state"});
        map.put("title", "考生考试信息");
        map.put("name", "考生考试信息");
        map.put("dataList", (Serializable) examNoticeErrorTemplateList);

        try {
            ExcelUtil.exportExcel(map, response);
            return true;
        } catch (Exception e) {
            log.error("下载考生考试模板失败",e);
            return false;
        }
    }


    /**
     * 根据学生id查询学生所有考试科目
     *
     * @param studentNo 学号
     * @return Itoo
     * @author 贾建清
     * @since 2.0.0 2019年1月1日17:20:34
     */
    @Override
    public List<ExamNoticeModel> queryExamNoticeByStudentNo(String studentNo) {
        return examNoticeDao.queryExamNoticeByStudentNo(studentNo);
    }

}
